dbt 的語法不只是 SQL,在 dbt 我們除了單純的 SQL 之外也混用了 Jinja 語法。
之前幾天用過的 {{ ref('model_name') }}
這種用大括號的語法就是 Jinja。
在 complie 時,我們的 Jinja-SQL 被翻譯成純 SQL 語法,後續才能在我們的 Data Platform 繼續執行create/insert/update 等工作。
我和很多人一樣,第一個用到的 Jinja 是 ref
function。
即使我在入門篇很不想提到 Jinja,但 ref
function 實在沒辦法不使用。
舉例來說
select * from {{ ref('stg_orders') }}
ref
function 會依照設定的 BigQuery project, dataset, schema,compile 出完整的 view 或 table 名稱。
在 Cloud IDE compile 出來的結果是
select * from `dbt-demo-2023`.`dbt_dev`.`stg_orders`
如果在正式環境跑,compile 出來的就會是正式環境所使用的 schema
select * from `dbt-demo-2023`.`dbt_prod`.`stg_orders`
如果在 dbt model 裡面,不寫 Jinja-SQL,而是直接寫出 compile 出來的純SQL,就無法在不同環境(dataset)中輕鬆切換了。
接下來我想藉由一個簡單的例子,說明 Jinja 的 For 迴圈 以及 If 判斷式的寫法。
假設有一段 SQL 如下,希望用 for loop 產出 attribute_1 ~ attribute_5
select
attribute_1,
attribute_2,
attribute_3,
attribute_4,
attribute_5
from table_1
如果用 Jinja 的 for 迴圈,類似這樣:
select
{% for i in range(1,6) %}
attribute_{{ i }},
{% endfor %}
from table_1
Compile 出來的結果可以看到,最後面的 attribute_5 最後多了一個逗號。
select
attribute_1,
attribute_2,
attribute_3,
attribute_4,
attribute_5,
from table_1
因此,我們可以加一個 if
判斷式 {% if not loop.last %},{% endif %}
,如果迴圈走到了最後,就不要加逗號。
select
{% for i in range(1,6) %}
attribute_{{ i }} {% if not loop.last %},{% endif %}
{% endfor %}
from table_1
Compile 的結果如下,可以看到沒有多餘的逗號了。
select
attribute_1 ,
attribute_2 ,
attribute_3 ,
attribute_4 ,
attribute_5
from table_1
再來就是我們可以稍微美化一下,去除多餘的空格。
將 {% ... %}
加入 -
,改成 {%- ... -%}
就可以去除頭尾空格,也可以只放一邊。例如:
select
{% for i in range(1,6) -%}
attribute_{{ i }} {%- if not loop.last %},{% endif %}
{% endfor %}
from table_1
Compile結果如下:
select
attribute_1,
attribute_2,
attribute_3,
attribute_4,
attribute_5
from table_1
今天只介紹了 Jinja 的基本語法,明天會再說明如何把重複的語法寫成 macro,也就是可以重複利用的 function。
明天的主題:dbt Macros。
歡迎加入 dbt community
對 dbt 或 data 有興趣 👋?歡迎加入 dbt community 到 #local-taipei 找我們,也有實體 Meetup 請到 dbt Taipei Meetup 報名參加